const express = require('express')
// 文件上传插件
var multipart = require('connect-multiparty');
// 声明express()示例
const app = express()
// token 
const jwt = require('jsonwebtoken');
// jsonwebtoken 的作用 ​核心功能：用于 ​生成（签名）和解析（验证）JWT。
var { expressjwt } = require("express-jwt");
// express-jwt 的作用 ​核心功能：作为 Express 中间件，​自动验证请求中的 JWT，并将解析后的数据挂载到 req.auth（或自定义属性）。
// redis
const { redis } = require("./database/redis")
const path = require('path');
// 配置跨域
var cors = require('cors')

app.use(cors())

// post请求中间件
app.use(express.json())
app.use(express.urlencoded())

// 设置上传目录
// multipart 中间件只负责处理文件上传，而不会自动提供静态文件服务。
app.use(multipart({ uploadDir: './public/uploads' }));

// 配置静态文件服务。使用 express.static 中间件来提供静态文件服务。
// 将 public 目录设置为静态文件目录，可以通过 /public 前缀访问。
app.use('/public', express.static(path.join(__dirname, 'public')));

// 按模块加载路由
const usersRouter = require("./router/usersRouter")
const activesRouter = require("./router/activesRouter")
const signUpRouter = require("./router/signUpRouter")
// token设置
// 测试token的中间件
// 如果在redis中搜到及存在的话，就证明token存在，就放行-next
app.use(function timeLog(req, res, next) {
    let { path } = req;
    // 模块路由中检测是否携带了 token
    if (path === '/users/adduser' || path === '/users/login') {
        next();
    } else if (req.path.startsWith('/public/uploads') && /\.(jpg|jpeg|png|gif)$/i.test(req.path)) {
        // 如果访问静态资源时候放行
        next()
    } else if (!req.headers.authorization) {
        return res.send({
            status: 403,
            message: "缺少token"
        });
    } else {
        try {
            const authHeader = req.headers.authorization;
            const token = authHeader ? authHeader.split(' ')[1] : null;
            console.log('未处理：', authHeader, '处理的：', token)

            // 第一步：直接解码 Token（不验证签名和过期时间）
            const decoded = jwt.decode(token, { complete: true });
            if (!decoded) {
                return res.status(401).json({ status: 401, message: "无效的token格式" });
            }

            // 第二步：获取用户 ID（即使 Token 过期也能拿到）
            const { id } = decoded.payload;
            const key = `uid:${id}`;

            // 第三步：手动检查 Token 是否过期
            try {
                // 重新验证 Token（包含过期检查），但忽略结果，只为捕获错误
                jwt.verify(token, '39qw89r23890', { ignoreExpiration: true });
            } catch (verifyError) {
                if (verifyError instanceof jwt.TokenExpiredError) {
                    // 记录过期状态，但继续检查 Redis
                    console.log('Token 已过期，但继续检查 Redis 状态');
                } else {
                    // 其他错误（如签名无效）
                    throw verifyError;
                }
            }

            // 第四步：查询 Redis 中的 Token
            redis.get(key, (err, storedToken) => {
                if (err) {
                    console.error('Redis 错误:', err);
                    return res.status(500).json({ status: 500, message: "服务器内部错误" });
                }

                if (storedToken === token) {
                    // Token 有效（即使 JWT 过期但 Redis 中仍有效，可放行或按业务逻辑处理）
                    next();
                } else {
                    res.status(403).json({
                        status: 403,
                        message: "token已失效，请重新登录！"
                    });
                }
            });

        } catch (error) {
            // 处理其他 JWT 错误（如篡改）
            if (error instanceof jwt.JsonWebTokenError) {
                return res.status(401).json({
                    status: 401,
                    message: "无效的token"
                });
            }
            next(error);
        }
    }
});
// 未处理： Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiLph5HlhYvmlq8iLCJpYXQiOjE3NDM1MTI5ODIsImV4cCI6MTc0MzU5OTM4Mn0._fxWV8nCLkJ89-t3mbILcTuwv2O35aVPwH7gp9mBNbw 
// 处理的： eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiLph5HlhYvmlq8iLCJpYXQiOjE3NDM1MTI5ODIsImV4cCI6MTc0MzU5OTM4Mn0._fxWV8nCLkJ89-t3mbILcTuwv2O35aVPwH7gp9mBNbw
app
    .use(expressjwt({
        algorithms: ["HS256"],
        credentialsRequired: false,//关键
        secret: "pwdxpx",//加密密钥，可换,'
    }));
// 路由路径配置
app.use('/users', usersRouter)
app.use('/actives', activesRouter)
app.use('/signUp', signUpRouter)


app.listen(3000, () => {
    console.log("服务器监听的地址是:http:127.0.0.1:3000")
})